package beastick.security.generic;

//Copyright 2008 Tofig Kareemov, estereos@gmail.com
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.

import beastick.utility.CUtilityMethods;

public class SecureHash extends CUtilityMethods
{
  public static final int Digest(Object oInput, int[] oOutput, int iGlue)
  {
    return Digest(oInput, oOutput, iGlue, true);
  }

  public static final int Digest(Object oInput, int[] oOutput, int iiGlue,
    boolean bInitialize)
  {
    if (!(IsValuable(oOutput) && (oOutput.length > 0)))
    {
      return iiGlue;
    }
    byte[] oByteInput = null;
    short[] oShortInput = null;
    int[] oIntInput = null;
    int i = 0;
    int i1 = 0;
    int iGlue = iiGlue;
    int iInputLength = 0;
    int iOutputLength = oOutput.length;
    if (oInput instanceof byte[])
    {
      oByteInput = (byte[]) oInput;
      iInputLength = oByteInput.length;
    }
    else if (oInput instanceof int[])
    {
      oIntInput = (int[]) oInput;
      iInputLength = oIntInput.length;
    }
    else if (oInput instanceof String)
    {
      try
      {
        return Digest(((String) oInput).getBytes("UNICODE"), oOutput, iGlue);
      }
      catch (Throwable t)
      {
        return Digest(((String) oInput).getBytes(), oOutput, iGlue);
      }
    }
    else if (oInput instanceof short[])
    {
      oShortInput = (short[]) oInput;
      iInputLength = oShortInput.length;
    }
    iGlue = Glue(iGlue, 0x55);
    if (bInitialize || (iInputLength <= 0))
    {
      if ((iGlue & 0x01) != 0)
      {
        for (i1 = 0; i1 < iOutputLength; ++i1)
        {
          iGlue = Glue(iGlue, i1);
          oOutput[i1] = iGlue;
        }
        ;
      }
      else
      {
        for (i1 = iOutputLength - 1; i1 >= 0; --i1)
        {
          iGlue = Glue(iGlue, i1);
          oOutput[i1] = iGlue;
        }
        ;
      }
    }
    if (iInputLength > 0)
    {
      i1 = -1;
      if (IsValuable(oByteInput))
      {
        for (i = 0; i < iInputLength; ++i)
        {
          i1 = i % iOutputLength;
          iGlue = Glue(iGlue, oByteInput[i] & 0xFF);
          oOutput[i1] = oOutput[i1] ^ iGlue;
        }
        ;
      }
      else if (IsValuable(oIntInput))
      {
        for (i = 0; i < iInputLength; ++i)
        {
          i1 = i % iOutputLength;
          iGlue = Glue(iGlue, oIntInput[i]);
          oOutput[i1] = oOutput[i1] ^ iGlue;
        }
        ;
      }
      else if (IsValuable(oShortInput))
      {
        for (i = 0; i < iInputLength; ++i)
        {
          i1 = i % iOutputLength;
          iGlue = Glue(iGlue, oShortInput[i]);
          oOutput[i1] = oOutput[i1] ^ iGlue;
        }
        ;
      }
      ++i1;
      for (; i1 < iOutputLength; ++i1)
      {
        iGlue = Glue(iGlue, i1);
        oOutput[i1] = oOutput[i1] ^ iGlue;
      }
      ;
    }
    ;
    iGlue = BackPath(oOutput, iGlue);
    return iGlue;
  }

  public static final int BackPath(int[] oOutput, int iGlue)
  {
    iGlue = Glue(iGlue, 0x55);
    int iGlueSave = iGlue;
    if (IsValuable(oOutput))
    {
      int iOutputLength = oOutput.length;
      iGlueSave = Glue(iGlue, oOutput[0]);
      for (int i = 0; i < iOutputLength; ++i)
      {
        iGlue = Glue(iGlue, oOutput[i]);
        oOutput[i] = iGlue;
      }
      ;
    }
    return iGlueSave;
  }

  public static final long HashLong(Object oInput)
  {
    int[] iHashArray = new int[SecureRandom.I_DOUBLELONG_BYTE_LENGTH];
    Digest(oInput, iHashArray, 0xcc);
    long iResult = 0;
    for (int i = 0; i < SecureRandom.I_LONG_BYTE_LENGTH; ++i)
    {
      iResult = (long) ((iResult << 8) | ((iHashArray[i] ^ iHashArray[SecureRandom.I_LONG_BYTE_LENGTH
        + i]) & 0xFF));
    }
    return iResult;
  }

  public static final int HashInt(Object oInput)
  {
    int[] iHashArray = new int[SecureRandom.I_DOUBLEINT_BYTE_LENGTH];
    Digest(oInput, iHashArray, 0xcc);
    int iResult = 0;
    for (int i = 0; i < SecureRandom.I_INT_BYTE_LENGTH; ++i)
    {
      iResult = (int) ((iResult << 8) | ((iHashArray[i] ^ iHashArray[SecureRandom.I_INT_BYTE_LENGTH
        + i]) & 0xFF));
    }
    return iResult;
  }

  public static final short HashShort(Object oInput)
  {
    int[] iHashArray = new int[SecureRandom.I_DOUBLESHORT_BYTE_LENGTH];
    Digest(oInput, iHashArray, 0xcc);
    short iResult = 0;
    for (int i = 0; i < SecureRandom.I_SHORT_BYTE_LENGTH; ++i)
    {
      iResult = (short) ((iResult << 8) | ((iHashArray[i] ^ iHashArray[SecureRandom.I_SHORT_BYTE_LENGTH
        + i]) & 0xFF));
    }
    return iResult;
  }

  public static final int Glue(int iiGlue, int iInput)
  {
    int iData = (iInput ^ ++iiGlue ^ 0xAA) & 0xFF;
    return ((iData << 1) | (iData >>> 7)) & 0xFF;
  }
}
/*
 * Trush Bin
 * 
 * 
 *  
 */